{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 38,
   "source": [
    "import numpy as np\r\n",
    "import pandas as pd\r\n",
    "from sklearn.datasets import load_iris\r\n",
    "from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score\r\n",
    "from sklearn.linear_model import LogisticRegression\r\n",
    "from sklearn.preprocessing import StandardScaler"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 1 导入数据"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "source": [
    "data,target = load_iris(return_X_y=True,as_frame=True)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "source": [
    "pd.isnull(data).any() # 判断样本数据是否有空\r\n"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "sepal length (cm)    False\n",
       "sepal width (cm)     False\n",
       "petal length (cm)    False\n",
       "petal width (cm)     False\n",
       "dtype: bool"
      ]
     },
     "metadata": {},
     "execution_count": 40
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "source": [
    "target.value_counts()/target.count() # 类别分布\r\n"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "0    0.333333\n",
       "1    0.333333\n",
       "2    0.333333\n",
       "Name: target, dtype: float64"
      ]
     },
     "metadata": {},
     "execution_count": 41
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "source": [
    "data.describe() # 查看数据分布"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sepal length (cm)</th>\n",
       "      <th>sepal width (cm)</th>\n",
       "      <th>petal length (cm)</th>\n",
       "      <th>petal width (cm)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>150.000000</td>\n",
       "      <td>150.000000</td>\n",
       "      <td>150.000000</td>\n",
       "      <td>150.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>5.843333</td>\n",
       "      <td>3.057333</td>\n",
       "      <td>3.758000</td>\n",
       "      <td>1.199333</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0.828066</td>\n",
       "      <td>0.435866</td>\n",
       "      <td>1.765298</td>\n",
       "      <td>0.762238</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>4.300000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.100000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>5.100000</td>\n",
       "      <td>2.800000</td>\n",
       "      <td>1.600000</td>\n",
       "      <td>0.300000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>5.800000</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>4.350000</td>\n",
       "      <td>1.300000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>6.400000</td>\n",
       "      <td>3.300000</td>\n",
       "      <td>5.100000</td>\n",
       "      <td>1.800000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>7.900000</td>\n",
       "      <td>4.400000</td>\n",
       "      <td>6.900000</td>\n",
       "      <td>2.500000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       sepal length (cm)  sepal width (cm)  petal length (cm)  \\\n",
       "count         150.000000        150.000000         150.000000   \n",
       "mean            5.843333          3.057333           3.758000   \n",
       "std             0.828066          0.435866           1.765298   \n",
       "min             4.300000          2.000000           1.000000   \n",
       "25%             5.100000          2.800000           1.600000   \n",
       "50%             5.800000          3.000000           4.350000   \n",
       "75%             6.400000          3.300000           5.100000   \n",
       "max             7.900000          4.400000           6.900000   \n",
       "\n",
       "       petal width (cm)  \n",
       "count        150.000000  \n",
       "mean           1.199333  \n",
       "std            0.762238  \n",
       "min            0.100000  \n",
       "25%            0.300000  \n",
       "50%            1.300000  \n",
       "75%            1.800000  \n",
       "max            2.500000  "
      ]
     },
     "metadata": {},
     "execution_count": 42
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2 分割数据集"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "source": [
    "X_train,X_test,y_train,y_test= train_test_split(data,target,test_size=0.3,random_state=42)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 2.1 标准化化数据"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "source": [
    "std = StandardScaler()\r\n",
    "std = std.fit(X_train)\r\n",
    "X_train = std.transform(X_train)\r\n",
    "X_test = std.transform(X_test)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 2.2 使用网格搜索"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "source": [
    "lr = LogisticRegression(penalty=\"l2\", random_state=420)\r\n",
    "\r\n",
    "params = {\r\n",
    "    \"solver\": [\"newton-cg\", \"lbfgs\", \"sag\", \"saga\"], # \"liblinear\"\r\n",
    "    \"C\": np.arange(0.1, 1.01, 0.01),\r\n",
    "    \"multi_class\":['ovr','multinomial']\r\n",
    "}\r\n",
    "\r\n",
    "grid_search = GridSearchCV(\r\n",
    "    lr, param_grid=params, cv=3, n_jobs=6, return_train_score=True\r\n",
    ")\r\n",
    "grid_search.fit(X_train, y_train)\r\n",
    "\r\n",
    "grid_search.best_params_, grid_search.best_estimator_, grid_search.best_score_"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "({'C': 0.9099999999999996,\n",
       "  'multi_class': 'multinomial',\n",
       "  'solver': 'newton-cg'},\n",
       " LogisticRegression(C=0.9099999999999996, multi_class='multinomial',\n",
       "                    random_state=420, solver='newton-cg'),\n",
       " 0.942857142857143)"
      ]
     },
     "metadata": {},
     "execution_count": 45
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 2.3 使用网格搜索的结果"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "source": [
    "lr = LogisticRegression(penalty=\"l2\", random_state=420, **grid_search.best_params_)\r\n",
    "lr = lr.fit(X_train, y_train)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "source": [
    "from sklearn import metrics"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "source": [
    "\r\n",
    "y_test_pred = lr.predict(X_test)\r\n",
    "accuracy = metrics.accuracy_score(y_test, y_test_pred)\r\n",
    "precision,recall,f1,_=metrics.precision_recall_fscore_support(y_test, y_test_pred, average='micro')\r\n",
    "accuracy,precision,recall,f1\r\n"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "(1.0, 1.0, 1.0, 1.0)"
      ]
     },
     "metadata": {},
     "execution_count": 48
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "source": [
    "y_train_pred = lr.predict(X_train)\r\n",
    "accuracy = metrics.accuracy_score(y_train, y_train_pred)\r\n",
    "precision,recall,f1,_=metrics.precision_recall_fscore_support(y_train, y_train_pred, average='macro')\r\n",
    "accuracy,precision,recall,f1"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "(0.9523809523809523, 0.9551656920077972, 0.954954954954955, 0.9549467275494673)"
      ]
     },
     "metadata": {},
     "execution_count": 59
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 2.4 计算精准率"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "source": [
    "def get_precision(y_test,y_pred,average='micro'):\r\n",
    "    y = y_test.copy().to_frame()\r\n",
    "    y.loc[:,'pred']=y_pred.copy()\r\n",
    "    target_lables = y_test.drop_duplicates().tolist()\r\n",
    "    cm = {}\r\n",
    "    for target_lable in target_lables:\r\n",
    "        target  =y[y.target==target_lable]\r\n",
    "        pred = y[y.pred==target_lable]\r\n",
    "        tp = target[target.target==target.pred]\r\n",
    "        fp = pred[pred.target!=target_lable]\r\n",
    "        fn = target[target.pred!=target_lable]\r\n",
    "        tn = y[((y.target!=target_lable)&(y.target==y.pred))]\r\n",
    "        cm.setdefault(target_lable,(tp,fp,fn,tn))\r\n",
    "    if average == 'micro':\r\n",
    "        tp_sum = sum([t[0].shape[0] for t in cm.values()])\r\n",
    "        fp_sum = sum([t[1].shape[0] for t in cm.values()])\r\n",
    "        precision = tp_sum/(tp_sum+fp_sum)\r\n",
    "    else:\r\n",
    "        p = []\r\n",
    "        for tp,fp,fn,tn in cm.values():\r\n",
    "            _p = tp.shape[0]/(tp.shape[0]+fp.shape[0])\r\n",
    "            p.append(_p)\r\n",
    "        precision = np.average(p)\r\n",
    "    return precision"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "source": [
    "# 训练集精准率\r\n",
    "get_precision(y_train,y_train_pred,average='micro')"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "0.9523809523809523"
      ]
     },
     "metadata": {},
     "execution_count": 62
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "source": [
    "# 测试集精准率\r\n",
    "get_precision(y_test,y_test_pred,average='micro')"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "metadata": {},
     "execution_count": 63
    }
   ],
   "metadata": {}
  }
 ],
 "metadata": {
  "orig_nbformat": 4,
  "language_info": {
   "name": "python",
   "version": "3.8.11",
   "mimetype": "text/x-python",
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "pygments_lexer": "ipython3",
   "nbconvert_exporter": "python",
   "file_extension": ".py"
  },
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3.8.11 64-bit ('ml': conda)"
  },
  "interpreter": {
   "hash": "747b44f12e4aca58ed843b3d1adc2185340143ea37ceaca70a8a99cbf8b68d0c"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}